package nbcp.db.mongo.entity

import jdk.nashorn.internal.ir.annotations.Ignore
import nbcp.base.comm.Require
import nbcp.base.extend.Slice
import nbcp.base.utils.CodeUtil
import org.apache.commons.codec.digest.DigestUtils



data class WxRefundParameterData(
        @Require
        var appid: String, //	是

        @Ignore
        @Require
        var AppSecret: String,

        @Require
        var mch_id: String,//是

        @Require
        var out_trade_no: String,//是     商户订单号

        @Require
        var out_refund_no:String,   //商户退款单号

        @Require
        var total_fee: Int, //是, 订单总金额

        @Require
        var refund_fee: Int,//是        退款金额

        //退款操作应在回调中执行
        @Require
        var notify_url :String = "",  //退款结果通知url   否

        var refund_desc :String = "",    //退款原因   否
        var refund_fee_type :String = "",    //退款货币种类   否
        var refund_account :String = ""    //退款资金来源   否

){
    @Require
    private var nonce_str: String = CodeUtil.getCode().Slice(0, 32)  //是
    private var sign: String = ""

    private var sign_type: String = "MD5" //否

    private fun check(): Boolean {
        var type = this::class.java;

        //TODO  原为   type.properties  具体待查
        type.fields
                .filter { it.getAnnotation(Require::class.java) != null }
                .forEach {
                    if (it.getAnnotation(Ignore::class.java) != null) {
                        return@forEach;
                    }

                    var value = it.get(this)
                    if (value is String && value.isNullOrEmpty()) {
                        return false;
                    }

                    if (value is Number && value.toInt() == 0) {
                        return false;
                    }
                }

        return true;
    }

    fun sign(): String {
        var type = this::class.java;
        var list = type.declaredFields
                .map {
                    var value = it.get(this)
                    if (value is String && value.isNullOrEmpty()) {
                        return@map it.name to ""
                    }

                    if (value is Number && value.toInt() == 0) {
                        return@map it.name to ""
                    }

                    if (it.getAnnotation(Ignore::class.java) != null) {
                        return@map it.name to ""
                    }

                    return@map it.name to "${it.name}=${value}"
                }
                .filter { it.second.isNotEmpty() }
                .sortedBy { it.first }
                .toMutableList();

        list.add("key" to "key=${AppSecret}");

        return DigestUtils.md5Hex(list.map { it.second }.joinToString("&")).toUpperCase()
    }

    fun toXml(): String {
        if (check() == false) return ""

        this.sign = sign();

        var type = this::class.java;

        return "<xml>" + type.declaredFields
                .map {
                    var value = it.get(this)
                    if (value is String && value.isNullOrEmpty()) {
                        return@map "";

                    }

                    if (value is Number && value.toInt() == 0) {
                        return@map "";
                    }

                    if (it.getAnnotation(Ignore::class.java) != null) {
                        return@map "";
                    }

                    return@map "<${it.name}><![CDATA[${value}]]></${it.name}>"
                }
                .filter { it.length > 0 }
                .joinToString("") + "</xml>";
    }
}